/* $Id$ */
/* vim: set filetype=verilog ts=8 sw=4 tw=132: */
/*****************************************************************************
 
              (c) Copyright 1987 - 2012,  VIA Technologies, Inc.       
                            ALL RIGHTS RESERVED                            
                                                                     
 This design and all of its related documentation constitutes valuable and
 confidential property of VIA Technologies, Inc.  No part of it may be
 reproduced in any form or by any means   used to make any transformation
 / adaptation / redistribution without the prior written permission from the
 copyright holders. 
 
------------------------------------------------------------------------------

  DESCRIPTION:

  FEATURES:

  TODO:

  AUTHORS:
     Shawn Fang
    
------------------------------------------------------------------------------
                             REVISION HISTORY
    $Log$

*****************************************************************************/
module memory(
    //outputs
    output [31:0] valM,
    output reg  [31:0] maddr,
    output wenable,
    output reg  [31:0] wdata,
    output renable,
    output reg   [2:0] stat,
    //inputs
    input  clock,
    input  reset,
    input  [3:0] icode,
    input  [3:0] ifun,
    input  [31:0] valE,
    input  [31:0] valA,
    input  [31:0] valP,
    input  [31:0] rdata,
    input  m_ok,
    input  i_ok,
    input  instrErr
    );

    assign renable=(icode==`IMRMOVL
		    ||icode==`IPOPL
		    ||icode==`IRET)?1'b1:1'b0;
    //always @ (i_ok or m_ok or icode)
    always @ (posedge clock or posedge reset)
    begin
	if(reset)
	    stat<=`SAOK;
	else
	begin
	    if(~i_ok || ~m_ok)
		stat<=`SADR;
	    else if(instrErr)
		stat<=`SINS;
	    else if(icode==`IHALT)
		stat<=`SHLT;
	    else
		stat<=`SAOK;
	end
    end

    always @ (icode or valE or valA)
    begin
	if(icode==`IRMMOVL
	    ||icode==`IPUSHL
	    ||icode==`ICALL
	    ||icode==`IMRMOVL)
	    maddr<=valE;
	else if(icode==`IPOPL||icode==`IRET)
	    maddr<=valA;
	else
	    maddr<=0;
    end

    assign valM=rdata;
    assign renable=(icode== `IMRMOVL
		    || icode==`IPOPL
		    || icode==`IRET)?1'b1:1'b0;
    assign wenable=(icode==`IRMMOVL
		    ||icode==`IPUSHL
		    ||icode==`ICALL)?1'b1:1'b0;
    always @ (icode or valA or valP)
    begin
	case(icode)
	    `IRMMOVL:wdata<=valA;
	    `IPUSHL:wdata<=valA;
	    `ICALL:wdata<=valP;
	    default:wdata<=0;
	endcase
    end

endmodule
